package com.woniuxy.coachservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.coachdao.mapper.CoachInfoMapper;
import com.woniuxy.coachdao.model.CoachInfo;
import com.woniuxy.coachdao.model.CoachLoginLog;
import com.woniuxy.coachmodel.dto.CoachLoginDto;
import com.woniuxy.coachmodel.form.ApiSearchCoachForm;
import com.woniuxy.coachmodel.form.UpdateCoachStateForm;
import com.woniuxy.coachmodel.param.*;
import com.woniuxy.coachservice.exception.CoachException;
import com.woniuxy.coachservice.service.CoachInfoService;
import com.woniuxy.core.status.CoachState;
import com.woniuxy.core.util.DateUtil;
import com.woniuxy.core.util.PageInfo;
import com.woniuxy.util.MyOssUtil;
import com.woniuxy.util.MyRedisKeyUtil;
import com.woniuxy.util.MyRedisUtil;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 教练 服务实现类
 * </p>
 *
 * @author 冉杰
 * @since 2024-01-15
 */
@Service
public class CoachInfoServiceImpl extends ServiceImpl<CoachInfoMapper, CoachInfo> implements CoachInfoService {

    @Resource
    private MyRedisUtil myRedisUtil;

    @Resource
    private MyRedisKeyUtil myRedisKeyUtil;
    @Resource
    private CoachInfoMapper coachInfoMapper;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private MyOssUtil myOssUtil;

    @Override
    public void sendRegisterCode(String phone) {
        if(myRedisUtil.exists(myRedisKeyUtil.sendRegisterInMinute(phone))){
            throw new CoachException(9002,"1分钟内已发送过验证码");
        }
        String total = myRedisUtil.get(myRedisKeyUtil.sendCodeTotalInHour(phone));
        if(total!=null&&Integer.parseInt(total)>=5){
            throw new CoachException(9003,"1小时内发送验证码超过限制");
        }
        QueryWrapper<CoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_phone",phone);
        CoachInfo coachInfo = coachInfoMapper.selectOne(wrapper);
        if(!BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(9001,"手机号已被注册");
        }
        rabbitTemplate.convertAndSend("coach_code_send_register",phone);
    }

    @Override
    public void register(CoachRegisterParam param) {
        String total = myRedisUtil.get(myRedisKeyUtil.errorTotal(param.getCoachPhone()));
        if(total!=null&&Integer.parseInt(total)>=5){
            myRedisUtil.del(myRedisKeyUtil.registerCodeKey(param.getCoachPhone()));
            myRedisUtil.del(myRedisKeyUtil.errorTotal(param.getCoachPhone()));
            throw new CoachException(9006,"错误输入验证码超过5次，请重新发送");
        }
        String code = myRedisUtil.get(myRedisKeyUtil.registerCodeKey(param.getCoachPhone()));
        if(!param.getPhoneCode().equals(code)){
            if(!myRedisUtil.exists(myRedisKeyUtil.errorTotal(param.getCoachPhone()))){
                myRedisUtil.set(myRedisKeyUtil.errorTotal(param.getCoachPhone()),"1",5*60);
            }else {
                myRedisUtil.increment(myRedisKeyUtil.errorTotal(param.getCoachPhone()));
            }
            throw new CoachException(9004,"验证码错误");
        }
        QueryWrapper<CoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_phone",param.getCoachPhone());
        CoachInfo coachInfo = coachInfoMapper.selectOne(wrapper);
        if(!BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(9001,"手机号已被注册");
        }
        QueryWrapper<CoachInfo> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("coach_account",param.getCoachAccount());
        CoachInfo coachInfo1 = coachInfoMapper.selectOne(wrapper1);
        if(!BeanUtil.isEmpty(coachInfo1)){
            throw new CoachException(9005,"用户名已被注册");
        }
        QueryWrapper<CoachInfo> wrapper2 = new QueryWrapper<>();
        wrapper2.eq("id_card",param.getIdCard());
        CoachInfo coachInfo2 = coachInfoMapper.selectOne(wrapper2);
        if(!BeanUtil.isEmpty(coachInfo2)){
            throw new CoachException(9006,"身份证号已被注册");
        }
        CoachInfo coachInfo3 = BeanUtil.toBean(param, CoachInfo.class);
        coachInfo3.setCoachState(CoachState.IS_ENABLE.getState());
        coachInfo3.setAuthState(CoachState.IS_NOT_AUTH.getState());
        String gender = getGenderByIdCard(param.getIdCard());
        coachInfo3.setCoachSex(gender);
        coachInfoMapper.insert(coachInfo3);
        myRedisUtil.del(myRedisKeyUtil.registerCodeKey(param.getCoachPhone()));
    }

    @Override
    public CoachLoginDto loginByAccountPass(CoachLoginByAccountPassParam param) {
        QueryWrapper<CoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_account",param.getCoachAccount());
        CoachInfo coachInfo = coachInfoMapper.selectOne(wrapper);
        if(BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(2001,"账号不存在");
        }
        if(!coachInfo.getCoachPass().equals(param.getCoachPass())){
            throw new CoachException(2002,"密码错误");
        }
        if(coachInfo.getCoachState()!= CoachState.IS_ENABLE.getState()){
            throw new CoachException(2003,"账号状态异常");
        }
        CoachLoginDto dto = BeanUtil.toBean(coachInfo, CoachLoginDto.class);
        CoachLoginLog loginLog = new CoachLoginLog();
        loginLog.setLoginAddr(param.getIpAddr());
        loginLog.setCoachId(coachInfo.getCoachId());
        loginLog.setCoachAccount(coachInfo.getCoachAccount());
        loginLog.setLoginTime(new Date().toString());
        rabbitTemplate.convertAndSend("coach_login_log",loginLog);
        return dto;
    }

    @Override
    public void sendLoginPhoneCode(String phone) {
        boolean flag = new LambdaQueryChainWrapper<CoachInfo>(coachInfoMapper)
                .eq(CoachInfo::getCoachPhone, phone).exists();
        if (!flag) throw new CoachException(40007,"手机号还未注册，请先注册");
        //查一下该手机号的验证码是否在1分钟之内
        if (myRedisUtil.exists(myRedisKeyUtil.sendLoginInMinute(phone))){
            throw new CoachException(40002,"短信发送过于频繁");
        }
        String total = myRedisUtil.get(myRedisKeyUtil.sendCodeTotalInHour(phone));
        if (StringUtils.hasLength(total)&&Integer.parseInt(total)>=5){
            throw new CoachException(40003,"1小时内发送次数超过上限");
        }
        rabbitTemplate.convertAndSend("coach_code_send_login",phone);
    }

    @Override
    public CoachLoginDto loginByPhoneCode(CoachLoginByPhoneCodeParam form) {
        CoachInfo coachInfo = new LambdaQueryChainWrapper<CoachInfo>(coachInfoMapper)
                .eq(CoachInfo::getCoachPhone, form.getCoachPhone()).one();
        if (BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(40007,"手机号还未注册，请先注册");
        }
        if(coachInfo.getCoachState()!=CoachState.IS_ENABLE.getState()){
            throw new CoachException(40008,"账号状态异常");
        }
        String total = myRedisUtil.get(myRedisKeyUtil.errorTotal(form.getCoachPhone()));
        //防止非法循环匹配验证码
        if (StringUtils.hasLength(total)&&Integer.parseInt(total)>=5){
            myRedisUtil.del(myRedisKeyUtil.loginCodeKey(form.getCoachPhone()));
            myRedisUtil.del(myRedisKeyUtil.errorTotal(form.getCoachPhone()));
            throw new CoachException(40006,"超过最大错误限次");
        }
        if (!form.getPhoneCode().equals(myRedisUtil.get(myRedisKeyUtil.loginCodeKey(form.getCoachPhone())))){
            if (!myRedisUtil.exists(myRedisKeyUtil.errorTotal(form.getCoachPhone()))){
                myRedisUtil.set(myRedisKeyUtil.errorTotal(form.getCoachPhone()),"1",5*60);
            }else {
                myRedisUtil.increment(myRedisKeyUtil.errorTotal(form.getCoachPhone()));
            }
            throw new CoachException(40004,"验证码错误");
        }
        CoachLoginDto coachLoginDto = BeanUtil.toBean(coachInfo, CoachLoginDto.class);
        //删除缓存里的验证码
        myRedisUtil.del(myRedisKeyUtil.loginCodeKey(form.getCoachPhone()));
        CoachLoginLog loginLog = new CoachLoginLog();
        loginLog.setLoginAddr(form.getIpAddr());
        loginLog.setCoachId(coachInfo.getCoachId());
        loginLog.setCoachAccount(coachInfo.getCoachAccount());
        loginLog.setLoginTime(DateUtil.dateTimeToString(new Date()));
        rabbitTemplate.convertAndSend("coach_login_log",loginLog);
        return coachLoginDto;
    }

    @Override
    public void uploadCoachAvatar(String url, Integer coachId) {
        CoachInfo coachInfo = coachInfoMapper.selectById(coachId);
        coachInfo.setCoachAvatar(url);
        coachInfoMapper.updateById(coachInfo);
    }

    @Override
    public void updateCoachAvatar(UpdateCoachAvatarParam param) throws IOException {
        CoachInfo coachInfo = coachInfoMapper.selectById(param.getCoachId());
        if(BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(4001,"教练不存在");
        }
        if(coachInfo.getCoachState()!=CoachState.IS_ENABLE.getState()){
            throw new CoachException(4002,"账号状态异常");
        }
        String fileType = FileTypeUtil.getType(param.getImage().getInputStream());
        if(!fileType.equals("jpg")&&!fileType.equals("png")){
            throw new CoachException(10086,"文件类型错误");
        }
        Snowflake snowflake = new Snowflake(1, 1);
        String prefix = snowflake.nextIdStr();
        String filename = prefix+"."+fileType;
        String url = myOssUtil.uploadFile(param.getImage().getInputStream(), filename, "ranjie11");
        String oldUrl = coachInfo.getCoachAvatar();
        coachInfo.setCoachAvatar(url);
        try {
            coachInfoMapper.updateById(coachInfo);
        } catch (Exception e) {
            myOssUtil.deleteFile("ranjie11", FileUtil.getName(oldUrl));
        }
        myOssUtil.deleteFile("ranjie11",FileUtil.getName(oldUrl));
    }

    @Override
    public void uploadCoachLicense(String url, Integer coachId) {
        CoachInfo coachInfo = coachInfoMapper.selectById(coachId);
        if(BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(1001,"该账号不存在");
        }
        if(coachInfo.getCoachState()!=CoachState.IS_ENABLE.getState()){
            throw new CoachException(1002,"账号状态异常");
        }
        coachInfo.setCoachLicense(url);
        coachInfoMapper.updateById(coachInfo);
    }

    /**
     * 完善修改个人简介
     * @param param
     */
    @Override
    public void refine(RefineParam param) {
        CoachInfo coachInfo = coachInfoMapper.selectById(param.getCoachId());
        if(BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(1001,"该账号不存在");
        }
        if(coachInfo.getCoachState()!=CoachState.IS_ENABLE.getState()){
            throw new CoachException(1002,"账号状态异常");
        }
        coachInfo.setCoachRemark(param.getCoachRemark());
        coachInfoMapper.updateById(coachInfo);
    }

    @Override
    public void checkOldPass(String oldPass, Integer coachId) {
        CoachInfo coachInfo = coachInfoMapper.selectById(coachId);
        if(BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(1001,"该账号不存在");
        }
        if(coachInfo.getCoachState()!=CoachState.IS_ENABLE.getState()){
            throw new CoachException(1002,"账号状态异常");
        }
        if(!coachInfo.getCoachPass().equals(oldPass)){
            throw new CoachException(1003,"老密码验证错误");
        }
    }

    @Override
    public void updatePass(UpdateCoachPassParam param) {
        CoachInfo coachInfo = coachInfoMapper.selectById(param.getCoachId());
        if(BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(1001,"该账号不存在");
        }
        if(coachInfo.getCoachState()!=CoachState.IS_ENABLE.getState()){
            throw new CoachException(1002,"账号状态异常");
        }
        if(coachInfo.getCoachPass().equals(param.getNewPass())){
            throw new CoachException(1003,"新密码与旧密码一致");
        }
        coachInfo.setCoachPass(param.getNewPass());
        coachInfoMapper.updateById(coachInfo);
    }

    @Override
    public void updateCoachPhone(UpdateCoachPhoneParam param) {
        QueryWrapper<CoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_phone",param.getNewPhone());
        CoachInfo coachInfo = coachInfoMapper.selectOne(wrapper);
        if(!BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(1001,"该手机号已注册");
        }
        CoachInfo coachInfo1 = coachInfoMapper.selectById(param.getCoachId());
        if(BeanUtil.isEmpty(coachInfo1)){
            throw new CoachException(1001,"该账号不存在");
        }
        if(coachInfo1.getCoachState()!=CoachState.IS_ENABLE.getState()){
            throw new CoachException(1002,"账号状态异常");
        }
        coachInfo1.setCoachPhone(param.getNewPhone());
        coachInfoMapper.updateById(coachInfo1);
    }

    @Override
    public void disableCoach(UpdateCoachStateForm form) {
        CoachInfo coachInfo = coachInfoMapper.selectById(form.getCoachId());
        if(BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(1001,"该账号不存在");
        }
        if(coachInfo.getCoachState()==CoachState.IS_DISABLED.getState()){
            throw new CoachException(1002,"该账号已禁用");
        }
        coachInfo.setCoachState(CoachState.IS_DISABLED.getState());
        coachInfoMapper.updateById(coachInfo);
    }

    @Override
    public void enableCoach(UpdateCoachStateForm form) {
        CoachInfo coachInfo = coachInfoMapper.selectById(form.getCoachId());
        if(BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(1001,"该账号不存在");
        }
        if(coachInfo.getCoachState()==CoachState.IS_ENABLE.getState()){
            throw new CoachException(1003,"该账号已启用");
        }
        coachInfo.setCoachState(CoachState.IS_ENABLE.getState());
        coachInfoMapper.updateById(coachInfo);
    }

    @Override
    public void auditCoach(UpdateCoachStateForm form) {
        CoachInfo coachInfo = coachInfoMapper.selectById(form.getCoachId());
        if(BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(1001,"该账号不存在");
        }
        if(ObjectUtil.isEmpty(coachInfo.getCoachAccount())
                ||ObjectUtil.isEmpty(coachInfo.getCoachAvatar())
                ||ObjectUtil.isEmpty(coachInfo.getCoachLicense())
                ||ObjectUtil.isEmpty(coachInfo.getCoachName())
                ||ObjectUtil.isEmpty(coachInfo.getCoachPhone())
                ||ObjectUtil.isEmpty(coachInfo.getIdCard())) throw new CoachException(1004,"信息尚未完善,认证失败");
        if(coachInfo.getCoachState()!=CoachState.IS_ENABLE.getState()){
            throw new CoachException(1002,"账号状态异常");
        }
        if(coachInfo.getAuthState()==CoachState.IS_AUTH.getState()){
            throw new CoachException(1003,"该账号已认证");
        }
        coachInfo.setAuthState(CoachState.IS_AUTH.getState());
        coachInfoMapper.updateById(coachInfo);
    }

    @Override
    public void refuseCoach(Integer coachId, String message) {
        CoachInfo coachInfo = coachInfoMapper.selectById(coachId);
        if(BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(1001,"该账号不存在");
        }
        if(coachInfo.getCoachState()!=CoachState.IS_ENABLE.getState()){
            throw new CoachException(1002,"账号状态异常");
        }
        if(coachInfo.getAuthState()==2){
            throw new CoachException(1003,"该账号已拒绝认证");
        }
        coachInfo.setCoachState(2);
        coachInfo.setMessage(message);
        coachInfoMapper.updateById(coachInfo);
    }

    @Override
    public CoachLoginDto viewPersonalInformation(Integer coachId) {
        CoachInfo coachInfo = coachInfoMapper.selectById(coachId);
        CoachLoginDto dto = BeanUtil.toBean(coachInfo, CoachLoginDto.class);
        return dto;
    }

    @Override
    public List<CoachLoginDto> venueSearchCoach() {
        QueryWrapper<CoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("auth_state",1);
        List<CoachInfo> list = coachInfoMapper.selectList(wrapper);
        List<CoachLoginDto> dtos = BeanUtil.copyToList(list, CoachLoginDto.class);
        return dtos;
    }

    @Override
    public PageInfo<CoachLoginDto> byPage(Integer pageNum, Integer pageSize, Integer venueId) {
        LambdaQueryWrapper<CoachInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CoachInfo::getVenueId,venueId);
        Page<CoachInfo> page = new Page<>(pageNum==null?1L:pageNum,pageSize==null?5L:pageSize);
        page(page,wrapper);
        PageInfo pageInfo = BeanUtil.toBean(page, PageInfo.class);
        pageInfo.setPages(page.getPages());
        pageInfo.setList(BeanUtil.copyToList(page.getRecords(),CoachLoginDto.class));
        return pageInfo;
    }

    @Override
    public PageInfo<CoachLoginDto> searchCoach(ApiSearchCoachForm form) {
        QueryWrapper<CoachInfo> wrapper = new QueryWrapper<>();
        wrapper.like(!BeanUtil.isEmpty(form.getCoachPhone()),"coach_phone",form.getCoachPhone());
        wrapper.eq(!BeanUtil.isEmpty(form.getCoachSex()),"coach_sex",form.getCoachSex());
        wrapper.like(!BeanUtil.isEmpty(form.getCoachName()),"coach_name",form.getCoachName());
        wrapper.eq(!BeanUtil.isEmpty(form.getCoachState()),"coach_state",form.getCoachState());
        wrapper.eq(!BeanUtil.isEmpty(form.getAuthState()),"auth_state",form.getAuthState());
        wrapper.eq(!BeanUtil.isEmpty(form.getVenueId()),"venue_id",form.getVenueId());
        Page<CoachInfo> page = new Page<>(form.getPageNum(),form.getPageSize());
        page(page,wrapper);
        List<CoachInfo> records = page.getRecords();
        List<CoachLoginDto> list = BeanUtil.copyToList(records, CoachLoginDto.class);
        PageInfo pageInfo = BeanUtil.toBean(page, PageInfo.class);
        pageInfo.setPages(page.getPages());
        pageInfo.setList(list);
        return pageInfo;
    }

    @Override
    public CoachLoginDto searchCoachByCoachId(Integer coachId) {
        CoachInfo coachInfo = coachInfoMapper.selectById(coachId);
        if(BeanUtil.isEmpty(coachInfo)){
            throw new CoachException(1001,"该账号不存在");
        }
        CoachLoginDto dto = BeanUtil.toBean(coachInfo, CoachLoginDto.class);
        return dto;
    }

    @Override
    public List<CoachLoginDto> searchAllCoachByCoachIds(List<Integer> coachIds) {
        QueryWrapper<CoachInfo> wrapper = new QueryWrapper<>();
        wrapper.in("coach_id",coachIds);
        List<CoachInfo> coachInfos = coachInfoMapper.selectList(wrapper);
        List<CoachLoginDto> dtos = BeanUtil.copyToList(coachInfos, CoachLoginDto.class);
        return dtos;
    }

    @Override
    public List<CoachLoginDto> venueSearchCoachByCoachIds(List<Integer> coachIds) {
        QueryWrapper<CoachInfo> wrapper = new QueryWrapper<>();
        wrapper.in("coach_id",coachIds);
        wrapper.eq("auth_state",CoachState.IS_AUTH.getState());
        List<CoachInfo> coachInfos = coachInfoMapper.selectList(wrapper);
        List<CoachLoginDto> dtos = BeanUtil.copyToList(coachInfos, CoachLoginDto.class);
        return dtos;
    }

    @Override
    public CoachLoginDto venueSearchCoachByCoachId(Integer coachId) {
        QueryWrapper<CoachInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_id",coachId);
        wrapper.eq("auth_state",CoachState.IS_AUTH.getState());
        CoachInfo coachInfo = coachInfoMapper.selectOne(wrapper);
        CoachLoginDto dto = BeanUtil.toBean(coachInfo, CoachLoginDto.class);
        return dto;
    }

    @Override
    public PageInfo<CoachLoginDto> searchCoachByVenueId(Integer pageSize,Integer pageNum,Integer venueId) {
        Page<CoachInfo> page = new Page<>(pageNum==null?1:pageNum, pageSize==null?4:pageSize);
//        QueryWrapper<CoachInfo> wrapper = new QueryWrapper<>();
        LambdaQueryWrapper<CoachInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CoachInfo::getVenueId,venueId);
        page(page,wrapper);
        PageInfo pageInfo = BeanUtil.toBean(page, PageInfo.class);
        pageInfo.setPages(page.getPages());
        pageInfo.setList(BeanUtil.copyToList(page.getRecords(),CoachLoginDto.class));
        return pageInfo;
    }

    @Override
    public List<CoachLoginDto> findCoachByVenueId(Integer venueId) {
        List<CoachInfo> list = new LambdaQueryChainWrapper<CoachInfo>(getBaseMapper())
                .eq(CoachInfo::getVenueId, venueId).list();
        List<CoachLoginDto> dtos = BeanUtil.copyToList(list, CoachLoginDto.class);
        return dtos;
    }



    public static String getGenderByIdCard(String idCard) {
        char genderChar = idCard.charAt(idCard.length() - 2); // 获取倒数第二位字符
        if (genderChar % 2 == 0) {
            return "女"; // 偶数表示女性
        } else {
            return "男"; // 奇数表示男性
        }
    }



}
